import urllib.parse
import json
from CAAi3dxClient import *


# 封装客户端，然后这里只负责登录登出
class CAAi3dxLoginClient:
    def __init__(self, client: CAAi3dxClient):
        self._client = client  # common client toolbox

    def login(self, username, password):
        try:
            # - Catch 3DPassport login web service URL from last redirect URL
            passport3ds_url_str = self._client.get_passport_server()

            # == == == == == == == == == == == == == == == == == == == == == == == == == == == == == ==
            # == STEP 1: Retrieve the login ticket
            passport3ds_lt_url_str = passport3ds_url_str + "/login?action=get_auth_params"

            # - Load URL (Assuming _client.get_url_loader().load_url is a method that performs HTTP requests)
            response = self._client.get_url_loader().load_url(passport3ds_lt_url_str, "GET", '')
            response_str = response.decode(self._client.ENCODING)

            print("Response Body:")
            print(response_str)

            # - Catch Login Ticket LT from response body
            lt_start = response_str.find("lt") + 5
            lt_end = response_str.find("\"", lt_start)
            lt = response_str[lt_start:lt_end]

            print(f"\n --> Login Ticket: {lt}\n")

            # == == == == == == == == == == == == == == == == == == == == == == == == == == == == == ==

            # == STEP 2: POST to 3DPassport CAS server
            username_enc = urllib.parse.quote(username, encoding=self._client.ENCODING)
            password_enc = urllib.parse.quote(password, encoding=self._client.ENCODING)
            post_data_str = f"lt={lt}&username={username_enc}&password={password_enc}"
            post_data = post_data_str.encode()

            # - Build 3DPassport login web service URL
            space3ds_url_str = self._client.get_3d_space_server() + '/'
            passport3ds_login_url_str = passport3ds_url_str + "/login?service=" + urllib.parse.quote(space3ds_url_str,
                                                                                                     encoding=self._client.ENCODING)

            # - Load URL with POST request
            encodage_form = "application/x-www-form-urlencoded;charset=UTF-8"
            response = self._client.get_url_loader().load_url(passport3ds_login_url_str, "POST", encodage_form,
                                                              post_data)

            response_str = response.decode(self._client.ENCODING)
            print("\nResponse Body:")
            print(response_str)

            spaceUrl = f"{self._client.get_3d_space_server()}/resources/modeler/pno/person?current=true&select=preferredcredentials&select=collabspaces"
            spaceRes = self._client.get_url_loader().load_url(spaceUrl, "GET", None, None)
            spaceResJson = json.loads(spaceRes)
            role = spaceResJson['preferredcredentials']['role']['name']
            collabspace = spaceResJson['preferredcredentials']['collabspace']['name']
            org = spaceResJson['preferredcredentials']['organization']['name']
            securityContext = f"{role}.{org}.{collabspace}"
            self._client.get_url_loader().set_security_context(securityContext)

            # Check for authentication error
            if "error.authentication.credentials.bad" in response_str:
                print("#--------------------")
                print("error.authentication.credentials.bad")
                raise Exception("Login error: check login or password values")

        except Exception as e:
            print(f"Error during login: {str(e)}")
            raise e

    def logout(self):
        try:
            # - Redirect output to a log file
            output_dir = self._client.get_out()
            if output_dir:
                output_file = open(output_dir + "logout.traces", "w", encoding=self._client.ENCODING)
                print = lambda *args, **kwargs: output_file.write(" ".join(map(str, args)) + "\n")

            # - Remove the SecurityContext
            self._client.get_url_loader().set_security_context(None)

            # - Execute Logout
            print("## logout:")
            swym_logout_url = self._client.get_passport_server() + "/logout"
            response = self._client.get_url_loader().load_url(swym_logout_url, "GET")

            response_str = response.decode(self._client.ENCODING)
            print("\nResponse Body:")
            print(response_str)
            print("## End Of logout.")

        except Exception as e:
            print(f"Error during logout: {str(e)}")
            raise e
